package com.mocha.gateway.route;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.coffee.core.JSONUtils;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * @author: songkui
 * @since 2022-01-11
 */
@Component
@Slf4j
public class MochaDynamicNacosRouteHandler {
    private final MochaApplicationEventPublisherAware dynamicRouteService;
    private ConfigService configService;

    public MochaDynamicNacosRouteHandler(MochaApplicationEventPublisherAware dynamicRouteService){
        this.dynamicRouteService = dynamicRouteService;
    }

    @Value("${mocha.route.nacos.data-id}")
    private String dataId;

    @Value("${mocha.route.nacos.group}")
    private String group = "DEFAULT_GROUP";


    @Value("${spring.cloud.nacos.config.username}")
    private String username;
    @Value("${spring.cloud.nacos.config.password}")
    private String password;

    @Value("${spring.cloud.nacos.config.namespace}")
    private String namespace;

    @Value("${spring.cloud.nacos.config.server-addr}")
    private String serverAddr;


    private long timeOut = 5000;

    @PostConstruct
    public void init() {
        log.info("Server start Gateway route init...");
        try{
            configService = initConfigService();
            if(configService == null){
                log.warn("Server start InitConfigService fail*******");
                return;
            }
            String configInfo = configService.getConfig(dataId, group, timeOut);
            log.info("------- Server start loading gateway route configInfo--------- \r\n{}",configInfo);
            List<RouteDefinition> definitionList = JSONUtils.parseArray(configInfo, RouteDefinition.class);
            for(RouteDefinition definition : definitionList){
                dynamicRouteService.add(definition);
            }
        } catch (Exception e) {
            log.error("Server start Init gateway route exception: {}", e);
        }
        dynamicRouteByNacosListener(dataId, group);
    }

    //NacosListener
    private void dynamicRouteByNacosListener (String dataId, String group){
        try {
            configService.addListener(dataId, group, new Listener()  {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("--------Newest gateway route info--------- \n\r{}",configInfo);
                    List<RouteDefinition> definitionList = JSONUtils.parseArray(configInfo, RouteDefinition.class);
                    log.info("Update  newest route start...... {}",definitionList.toString());
                    dynamicRouteService.updateListByALL(definitionList);
                }
                @Override
                public Executor getExecutor() {
                    log.info("getExecutor\n\r");
                    return null;
                }
            });
        } catch (NacosException e) {
            log.error("Listener to Nacos gateway route exception: {}",e);
        }
    }

    private ConfigService initConfigService(){
        try{
            Properties properties = new Properties();
            properties.setProperty("serverAddr", serverAddr);
            properties.setProperty("namespace", namespace);
            properties.setProperty("username", username);
            properties.setProperty("password", password);
            return configService= NacosFactory.createConfigService(properties);
        } catch (Exception e) {
            log.error("Init ConfigService Exception: ",e);
            return null;
        }
    }


}
